home *** CD-ROM | disk | FTP | other *** search
- // menu.cpp
-
- #include "menu.h"
- #include "menu_item.h"
-
- #include "drawing.h"
- #include "events.h"
- #include "Finder_res.h"
-
- // constants
- const unsigned short left_margin = 3;
- const unsigned short right_margin = 3;
- const int divider_height = 5;
- const int shortcut_width = 16;
- const int shortcut_icon_width = 9;
-
- //
- // constructor
- //
- menu::menu( char* in_title, int in_bitmap_id, int x, int y, int baseline, int height, view* in_superview ):
- pane(in_superview)
- {
- // variables
- int unused, width;
- unsigned short length;
-
- // store member varibles
- if (in_title==NULL) {
- m_title[0] = 0;
- } else {
- StrCopy( m_title, in_title );
- }
- m_bitmap = in_bitmap_id;
- m_baseline = baseline;
- m_selected = false;
- m_open = false;
- m_saved_bits = NULL;
- m_items = NULL;
- m_selected_item = 0;
-
- length = StrLen(m_title);
- if (length==0) {
- get_bitmap_dimensions(in_bitmap_id, unused, width);
- // add margins
- width += left_margin + right_margin;
- } else {
- width = left_margin + FntCharsWidth(m_title, length) + right_margin;
- }
-
- // determine dimensions
- m_bounds.topLeft.x = x;
- m_bounds.topLeft.y = y;
- m_bounds.extent.x = short(width);
- m_bounds.extent.y = height;
- }
-
- //
- // destructor
- //
- menu::~menu(){
- while (m_items!=NULL)
- delete m_items;
- }
-
- //
- // add_item()
- //
- void
- menu::add_item (char* in_item, long in_id, char in_shortcut) {
- new menu_item (in_item, in_id, in_shortcut, &m_items);
- }
-
-
- //
- // draw_self()
- //
- void
- menu::draw_self() {
- // variables
- int x = m_bounds.topLeft.x + int(left_margin);
- int y = m_bounds.topLeft.y + m_baseline;
- int length = int(StrLen(m_title));
-
- if (length==0) {
- draw_bitmap (m_bitmap, x, y, left_align, bottom_align);
- } else {
- draw_string (m_title, x, y, left_align, baseline_align);
- }
- m_selected = false;
- }
-
- //
- // click_self()
- //
- Boolean
- menu::click_self(int x, int y) {
- #pragma unused (x, y)
-
- // return false so menu bar can handle click
- return false;
- }
-
- //
- // still_down_self()
- //
- Boolean
- menu::still_down_self(int x, int y) {
- int menu_bar_top = m_bounds.topLeft.y;
- int menu_bar_bottom = menu_bar_top + m_bounds.extent.y;
-
- // draw menu here in order to delay opening by one iteration,
- // in order to alllow restore_bits to go to all menus first.
- if (m_selected and not m_open) {
- save_bits();
- draw_menu();
- m_open = true;
- m_selected_item = 0;
- }
-
- if ((menu_bar_top<=y) && (y<menu_bar_bottom)) {
- if ( RctPtInRectangle(x, y, &m_bounds) != m_selected ) {
- WinInvertRectangle (&m_bounds, 0);
- m_selected = not m_selected;
-
- if (not m_selected) {
- // close menu
- restore_bits();
- m_open = false;
- m_selected_item = 0;
- }
- }
- } else if (m_open) {
- // track pen through open menu
- int index = get_item_hit (x, y);
- select_menu_item (index);
- }
-
- return false;
- }
-
- //
- // pen_up_self()
- //
- Boolean
- menu::pen_up_self(int x, int y) {
- #pragma unused (x, y)
- menu_item* item = NULL;
- int index;
- int id = 0;
-
- // if this menu is open, see if any selection was made
- if (m_open) {
- index = get_item_hit (x, y);
- if (index!=0) {
- item = get_item(index);
- if (item!=NULL) {
- id = item->get_id();
- }
- }
- }
-
- // un-invert title if inverted
- if (m_selected) {
- WinInvertRectangle (&m_bounds, 0);
- restore_bits();
- m_selected = false;
- m_open = false;
- }
-
- // send command down the chain of command
- if (id!=0) {
- send_menu_event (id, false, x, y);
- }
-
- return false;
- }
-
- #pragma mark -
-
- //
- // get_menu_dimensions()
- //
- void
- menu::get_menu_dimensions( int& height, int& width ) {
- menu_item* item = m_items;
- int linespace = FntLineHeight();
- int linewidth;
- unsigned short length;
- char s[64];
-
- height = 0;
- width = 0;
- while (item!=NULL) {
- item->get_text(s);
- if (StrCompare(s, "-")==0) {
- height += divider_height;
- } else {
- height += linespace;
- length = StrLen(s);
- linewidth = FntCharsWidth(s, length) + left_margin + right_margin;
- if (item->get_shortcut() != 0)
- linewidth += shortcut_width;
- if (linewidth > width)
- width = linewidth;
- }
- item = (menu_item*) (item->get_next());
- }
- }
-
- //
- // get_menu_content_rect()
- //
- void
- menu::get_menu_content_rect( RectangleType* r ) {
- int height, width;
-
- get_menu_dimensions (height, width);
- r->topLeft.x = m_bounds.topLeft.x + 1;
- r->topLeft.y = m_bounds.topLeft.y + m_bounds.extent.y + 1;
- r->extent.x = width;
- r->extent.y = height;
- }
-
- //
- // get_menu_frame_rect()
- //
- void
- menu::get_menu_frame_rect( RectangleType* r ) {
- get_menu_content_rect (r);
- r->topLeft.x--;
- r->topLeft.y--;
- r->extent.x += 3;
- r->extent.y += 3;
- }
-
- //
- // draw_menu()
- //
- void
- menu::draw_menu( ) {
- RectangleType r;
- PointType s, e;
-
- get_menu_content_rect(&r);
-
- // check if rectangle is big enough
- if ((r.extent.x<=2) || (r.extent.y<=2))
- return;
-
- // draw bottom shadow
- s.x = r.topLeft.x + 1;
- s.y = r.topLeft.y + r.extent.y + 1;
- e.x = r.topLeft.x + r.extent.x + 1;
- e.y = s.y;
- WinDrawLine(s.x, s.y, e.x, e.y);
-
- // draw right shadow
- s.x = e.x;
- s.y = r.topLeft.y + 2;
- WinDrawLine(s.x, s.y, e.x, e.y);
-
- // draw rectangle frame
- WinDrawRectangleFrame (simpleFrame, &r);
-
- // erase contents
- WinEraseRectangle(&r, 0);
-
- // draw text
- draw_menu_items();
- }
-
- //
- // draw_menu_items()
- //
- void
- menu::draw_menu_items( ) {
- menu_item* item = m_items;
- int linespace = FntLineHeight();
- int shortcut_x, shortcut_letter_x;
- int x, y;
- int height, width, baseline;
- char s[64];
- char shortcut_letter;
-
- x = m_bounds.topLeft.x + 1;
- y = m_bounds.topLeft.y + m_bounds.extent.y + 1;
- get_menu_dimensions(height, width);
- shortcut_x = x + width - shortcut_width - right_margin;
- shortcut_letter_x = shortcut_x + shortcut_icon_width;
- baseline = FntBaseLine();
-
- while (item!=NULL) {
- item->get_text(s);
- if (StrCompare(s, "-")==0) {
- WinDrawGrayLine( x, y+divider_height/2, x+width-1, y+divider_height/2);
- y += divider_height;
- } else {
- draw_string(s, x+left_margin, y, left_align, top_align);
- shortcut_letter = item->get_shortcut();
- if (shortcut_letter!=0) {
- draw_bitmap(ShortcutBitmap, shortcut_x, y+baseline, left_align, bottom_align);
- draw_char(shortcut_letter, shortcut_letter_x, y, left_align, top_align);
- }
- y += linespace;
- }
- item = (menu_item*) (item->get_next());
- }
- }
-
- //
- // select_menu_item()
- //
- void
- menu::select_menu_item( int item ) {
- if (m_selected_item==item) return;
-
- if (m_selected_item!=0)
- invert_menu_item(m_selected_item);
- if (item != 0)
- invert_menu_item(item);
-
- m_selected_item = item;
- }
-
- //
- // invert_menu_item()
- //
- void
- menu::invert_menu_item( int item ) {
- RectangleType r;
-
- get_item_rect( item, &r );
- WinInvertRectangle( &r, 0 );
- }
-
- //
- // get_item_hit()
- //
- int
- menu::get_item_hit( int x, int y ) {
- int max = count_items();
- int i;
- RectangleType r;
- menu_item* item = NULL;
-
- for (i=1; i<=max; i++) {
- get_item_rect(i, &r);
- if (RctPtInRectangle ( x, y, &r )) {
- item = get_item(i);
- if (item!=NULL)
- if (item->get_enabled()==true) {
- return i;
- } else {
- return 0;
- }
- }
- }
- return 0;
- }
-
- //
- // get_item_rect()
- //
- void
- menu::get_item_rect( int index, RectangleType* r ) {
- menu_item* item = m_items;
- char s[64];
- int i=1;
- int linespace = FntLineHeight();
- int y, height;
-
- get_menu_content_rect(r);
- y = r->topLeft.y;
-
- while (item!=NULL) {
- item->get_text(s);
- if (StrCompare(s, "-")==0) {
- height = divider_height;
- } else {
- height = linespace;
- }
- r->extent.y = height;
- if (i==index) {
- // item found, return its rect
- r->topLeft.y = y;
- r->extent.y = height;
- return;
- }
- y += height;
- i++;
- item = (menu_item*) (item->get_next());
- }
-
- // item not found, return empty rect
- r->topLeft.x = 0;
- r->topLeft.y = 0;
- r->extent.x = 0;
- r->extent.y = 0;
- return;
- }
-
- //
- // count_items()
- //
- int
- menu::count_items() {
- menu_item* item = m_items;
- int i=0;
-
- while (item!=NULL) {
- i++;
- item = (menu_item*) (item->get_next());
- }
-
- return i;
- }
-
- //
- // get_item()
- //
- menu_item*
- menu::get_item(int index) {
- menu_item* item = m_items;
- int i=0;
-
- while (item!=NULL) {
- i++;
- if (i==index)
- break;
- item = (menu_item*) (item->get_next());
- }
-
- return item;
- }
-
- #pragma mark -
-
- //
- // save_bits()
- //
- void
- menu::save_bits( ) {
- // variables
- unsigned short err;
- RectangleType r;
-
- // calculate rectangle
- get_menu_frame_rect (&r);
- // dispose of any previously saved bits
- if (m_saved_bits!=NULL) {
- restore_bits();
- }
- // save rectangle
- m_saved_bits = WinSaveBits (&r, &err);
- }
-
- //
- // restore_bits()
- //
- void
- menu::restore_bits( ) {
- RectangleType r;
-
- // calculate rectangle
- get_menu_frame_rect (&r);
- // restore bits
- if (m_saved_bits!=NULL)
- WinRestoreBits (m_saved_bits, r.topLeft.x, r.topLeft.y);
- m_saved_bits = NULL;
- }
-